home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cocktail / lalr.lha / lalr / src / Lookahead.mi < prev    next >
Text File  |  1992-08-18  |  16KB  |  715 lines

  1. (* compute LALR(1) lookahead sets *)
  2.  
  3. (* $Id: Lookahead.mi,v 2.3 1992/08/07 15:22:49 grosch rel $ *)
  4.  
  5. (* $Log: Lookahead.mi,v $
  6.  * Revision 2.3  1992/08/07  15:22:49  grosch
  7.  * allow several scanner and parsers; extend module Errors
  8.  *
  9.  * Revision 2.2  1991/11/21  14:53:14  grosch
  10.  * new version of RCS on SPARC
  11.  *
  12.  * Revision 2.1  91/09/23  11:48:22  grosch
  13.  * renamed module LALR to Lookahead
  14.  * 
  15.  * Revision 2.0  91/03/08  18:31:46  grosch
  16.  * turned tables into initialized arrays (in C)
  17.  * moved mapping tokens -> strings from Errors to Parser
  18.  * changed interface for source position
  19.  * 
  20.  * Revision 1.1  90/06/12  16:54:24  grosch
  21.  * renamed main program to lalr, added { } for actions, layout improvements
  22.  * 
  23.  * Revision 1.0     88/10/04  14:36:29  vielsack
  24.  * Initial revision
  25.  * 
  26.  *)
  27.  
  28. IMPLEMENTATION MODULE Lookahead;
  29.  
  30. FROM SYSTEM    IMPORT ADR, TSIZE;
  31. FROM Limits    IMPORT MaxShortCard;
  32. FROM Errors    IMPORT eFatal, eInformation, eString, eInternal, ErrorMessage, ErrorMessageI;
  33. FROM DynArray    IMPORT MakeArray, ExtendArray;
  34. FROM Sets    IMPORT tSet, MakeSet, ReleaseSet, AssignEmpty, Include, Exclude,
  35.             Extract, Union, Assign, IsElement, IsEmpty, ForallDo;
  36. FROM Strings    IMPORT tString, ArrayToString;
  37. FROM Automaton    IMPORT tIndex, tStateIndex, tItemIndex, tProdIndex, tItemIndexList,
  38.             tProduction, tRep, tItem, StartSymbol, ItemIndex, ItemArrayPtr,
  39.             ProdList, ProdArrayPtr, StateIndex, StateArrayPtr;
  40. FROM Check    IMPORT CheckForConflicts;
  41. FROM Positions    IMPORT NoPosition;
  42. FROM TokenTab    IMPORT MINTerm, MAXTerm, MINNonTerm, MAXNonTerm, Vocabulary, Terminal,
  43.             NonTerminal, TokenError, TokenType, GetTokenType, TokenToSymbol;
  44.  
  45.   CONST
  46.     eConflict    = 64;
  47.     eNotLRk    = 62;
  48.  
  49.   VAR
  50.     Nullables        : tSet;
  51.     reportedError    : BOOLEAN;
  52.  
  53.   PROCEDURE ComputeLALR;
  54.     BEGIN
  55.       ComputeNullables;            (* A *)
  56.       MarkRep; 
  57.       ComputeDR;            (* B *)
  58.       ComputeReads;            (* C *)
  59.       Digraph (TreatReadConflict);    (* D *)
  60.       CheckReadSets;
  61.       ComputeIncludesAndLookback;    (* E *)
  62.       Digraph (TreatFollowConflict);    (* F *)
  63.       ComputeLA;            (* G *)
  64.       CheckForConflicts (NoConflict);    (* H *)
  65.     END ComputeLALR;
  66.  
  67.   PROCEDURE ComputeNullables;
  68.  
  69.   (* Berechne die Nichtterminale welche nullable sind *)
  70.  
  71.     VAR
  72.       todo    : tSet;        (* noch zu ueberpruefende Nichterminale *)
  73.       success    : BOOLEAN;    (* hatte der letzte Schritt Erfolg *)
  74.       t        : Terminal;
  75.       nt    : NonTerminal;
  76.  
  77.     PROCEDURE IsYetNullable (nt: CARDINAL);
  78.       VAR
  79.     u, i    : tIndex;
  80.     pn    : tProdIndex;
  81.     prod    : tProduction;
  82.     ri    : Vocabulary;
  83.     t    : Terminal;
  84.     localsuccess    : BOOLEAN;
  85.       BEGIN 
  86.     WITH ProdList[nt] DO
  87.       u := Used;
  88.  
  89.       (* Betrachte alle Produktionen mit linker Seite nt *)
  90.  
  91.       localsuccess := FALSE;
  92.       pn := 1;
  93.       WHILE (pn <= u) AND NOT localsuccess DO
  94.  
  95.         (* Auswahl der einzelnen Produktion *)
  96.  
  97.         prod := ADR(ProdArrayPtr^[Array^[pn].Index]);
  98.         WITH prod^ DO
  99.  
  100.           (* Pruefe ob rechte Seite in Nullables* liegt *)
  101.  
  102.           localsuccess := TRUE;
  103.           i := 1;
  104.  
  105.           WHILE (i <= Len) AND localsuccess DO
  106.         ri := Right [i];
  107.         localsuccess := IsElement (ri,Nullables);
  108.         INC (i);
  109.           END;
  110.         END;
  111.         INC (pn);
  112.       END;
  113.     END;
  114.  
  115.     IF localsuccess THEN
  116.       Include (Nullables, nt);
  117.       Exclude (todo, nt);
  118.       success := TRUE;
  119.     END;
  120.       END IsYetNullable;
  121.  
  122.     BEGIN 
  123.       MakeSet (todo,MAXNonTerm);
  124.       MakeSet (Nullables,MAXNonTerm);
  125.  
  126.       (* todo = Menge aller Nichtterminale *)
  127.  
  128.       FOR nt := MINNonTerm TO MAXNonTerm DO
  129.     IF GetTokenType (nt) = NonTerm THEN
  130.       Include (todo,nt);
  131.     END;
  132.       END;
  133.  
  134.       (* Nullables := { } *)
  135.  
  136.       REPEAT
  137.     success := FALSE;
  138.  
  139.     (* Pruefe ob jetzt ein weiteres *)
  140.     (* Nichtterminal terminalisierbar ist *)
  141.  
  142.     FOR nt := MINNonTerm TO MAXNonTerm DO
  143.       IF IsElement (nt, todo) THEN
  144.         IsYetNullable (nt);
  145.       END;
  146.     END;
  147.       UNTIL NOT success;    (* solange bis sich nichts aendert *)
  148.       ReleaseSet (todo);
  149.     END ComputeNullables;
  150.   
  151.   PROCEDURE MarkRep;
  152.  
  153.   (* Markiert Items die eine Uebergang oder eine Reduktion repraesentieren *)
  154.  
  155.     VAR 
  156.       si,s    : tStateIndex;
  157.       p        : tProduction;
  158.       reps    : tSet;
  159.       i        : tItemIndex;
  160.       RepArray    : ARRAY Vocabulary OF tItemIndex;
  161.       voc    : Vocabulary;
  162.     BEGIN
  163.       MakeSet (reps,MAXNonTerm);
  164.       si := StateIndex;
  165.       FOR s:=1 TO si DO
  166.     AssignEmpty (reps);
  167.     WITH StateArrayPtr^[s] DO
  168.       FOR i := Items TO Items + Size - 1 DO
  169.         WITH ItemArrayPtr^[i] DO 
  170.           p := ADR(ProdArrayPtr^[Prod]);
  171.           IF Pos >= p^.Len THEN
  172.         RepNo := i;
  173.         Rep := RedRep;
  174.           ELSE
  175.         (* wird in Automaton beim Einrichten erledigt 
  176.         *** voc := p^.Right[Pos+1];
  177.         *** Read := voc;
  178.         *)
  179.         voc := Read;
  180.         IF IsElement (voc,reps) THEN
  181.           Rep := NoRep;
  182.           RepNo := RepArray [voc];
  183.         ELSIF (voc >= MINTerm) AND (voc <= MAXTerm) THEN
  184.           RepArray [voc] := i;
  185.           RepNo := i;
  186.           Rep := TermRep;
  187.           Include (reps,voc);
  188.         ELSE (* NonTerminal *)
  189.           RepArray [voc] := i;
  190.           RepNo := i;
  191.           Rep := NonTermRep;
  192.           Include (reps,voc);
  193.         END;
  194.           END;
  195.  
  196.           (* nur fuer diese Items werden Sets benoetigt *)
  197.  
  198.           IF (Rep = RedRep) OR (Rep=NonTermRep) THEN
  199.         MakeSet (Set,MAXTerm);
  200.           END;
  201.         END;
  202.       END;
  203.     END;
  204.       END;
  205.       ReleaseSet (reps);
  206.     END MarkRep;
  207.  
  208.   PROCEDURE ComputeDR;
  209.  
  210.   (* Berechnung der "direct read symbols" (DR) *)
  211.   (* DR (p,A) := { t in T | p -A-> r -t-> }    *)
  212.     
  213.     VAR
  214.       maxItem    : tItemIndex;
  215.       pAIndex    : tItemIndex;
  216.       pA         : tItem;
  217.       pAProd    : tProduction;
  218.       r        : tStateIndex;
  219.       ir    : tItemIndex;
  220.     BEGIN
  221.       maxItem := ItemIndex;
  222.       FOR pAIndex := 1 TO maxItem DO 
  223.     
  224.     (* fuer alle Item - ein Item entspricht (p,A) *)
  225.  
  226.     pA := ItemArrayPtr^[pAIndex];
  227.  
  228.     (* pruefe ob pA einen Nichtterminaluebergang  repraesentiert *)
  229.  
  230.     pAProd := ADR(ProdArrayPtr^[pA.Prod]);    (* zugh. Produktion *)
  231.  
  232.     IF (pA.Rep = NonTermRep) THEN
  233.     
  234.       (* Bestimme r *)
  235.  
  236.       r := pA.Next;
  237.  
  238.       (* Berechne DR (p,A) als Menge aller in r lesbaren Terminale *)
  239.  
  240.       WITH StateArrayPtr^[r] DO   (* Zustand r *)
  241.         FOR ir := Items TO Items + Size - 1 DO 
  242.           WITH ItemArrayPtr^[ir] DO     (* ein Item von r *)
  243.         IF Rep = TermRep THEN
  244.           Include (ItemArrayPtr^[pAIndex].Set,Read);
  245.         END;
  246.           END;        (* ein Item von r *)
  247.         END;          (* Zustand r *)
  248.       END;
  249.     END;
  250.       END;
  251.     END ComputeDR;
  252.  
  253.  
  254.   PROCEDURE ComputeReads;
  255.  
  256.   (* (p,A) reads (r,C)    falls  p -A-> r -C-> and  C => epsilon *)
  257.  
  258.     VAR
  259.       pA, rC    : tItemIndex;
  260.       r        : tStateIndex;
  261.       maxItem    : tItemIndex;
  262.     BEGIN
  263.  
  264.       (* fuer alle Items die einen Nichterminaluebergang repraesentiren *)
  265.  
  266.       maxItem := ItemIndex;
  267.       FOR pA := 1 TO maxItem DO
  268.     IF ItemArrayPtr^[pA].Rep = NonTermRep THEN
  269.  
  270.       (* Berechne r *)
  271.  
  272.       r := ItemArrayPtr^[pA].Next;
  273.  
  274.       (* Berechne zugh. rC's *)
  275.  
  276.       FOR rC := StateArrayPtr^[r].Items TO 
  277.             StateArrayPtr^[r].Items + StateArrayPtr^[r].Size - 1 DO
  278.         
  279.         IF ItemArrayPtr^[rC].Rep = NonTermRep THEN    
  280.  
  281.           (* Pruefe ob C => Epsilon *)
  282.  
  283.           IF IsElement (ItemArrayPtr^[rC].Read,Nullables) THEN
  284.  
  285.         (* gueltiges rC gefunden *)
  286.         (* Fuege rC zur Relation hinzu *)
  287.  
  288.         PutInRelation (pA, rC);
  289.           
  290.           END;
  291.         END;
  292.       END;
  293.     END;
  294.       END;
  295.     END ComputeReads;
  296.  
  297.   PROCEDURE CheckReadSets;
  298.     VAR Item, MaxItem    : tItemIndex;
  299.     BEGIN
  300.       MaxItem := ItemIndex;
  301.       FOR Item := 1 TO MaxItem DO
  302.     WITH ItemArrayPtr^[Item] DO
  303.       IF Rep = NonTermRep THEN
  304.         IF IsEmpty (Set) THEN
  305.           EmptyReadSet := TRUE;
  306.         ELSE
  307.           EmptyReadSet := FALSE;
  308.           MakeSet (ReadSet,MAXTerm);
  309.           Assign (ReadSet,Set);
  310.         END;
  311.       END;
  312.     END;
  313.       END;
  314.     END CheckReadSets;
  315.  
  316.   PROCEDURE Digraph (TreatConflict: ConflictProc);
  317.     VAR x, maxItem    : tItemIndex;
  318.     BEGIN
  319.  
  320.       (* let S be an initially empty stack OF elements of X *)
  321.  
  322.       ClearItemStack;
  323.  
  324.       (* let N be an ARRAY OF zeros indexd by elements of X *)
  325.  
  326.       ClearNumbers;
  327.  
  328.       (* for x in X such that N x = 0 DO *)
  329.  
  330.       maxItem := ItemIndex;
  331.       FOR x := 1 TO maxItem DO
  332.     WITH ItemArrayPtr^[x] DO
  333.       IF Number = 0 THEN
  334.         Traverse (x,TreatConflict);
  335.       END;
  336.     END;
  337.       END;
  338.     END Digraph;
  339.  
  340.   PROCEDURE Traverse ( x: tItemIndex; TreatConflict: ConflictProc);
  341.     VAR
  342.       d        : CARDINAL;
  343.       ArrayIndex: tIndex;
  344.       yIndex    : tItemIndex;
  345.       u        : tIndex;
  346.       Top    : tItemIndex;
  347.       EmptyCycle,
  348.       cyclic    : BOOLEAN;
  349.     BEGIN
  350.       WITH ItemArrayPtr^[x] DO
  351.       
  352.     (* Push x on S *)
  353.  
  354.     PushItem (x);
  355.  
  356.     (* con d: Depth of S *)
  357.  
  358.     d := ItemDepth();
  359.  
  360.     (* N x <- d ;    F x <- F' x *)
  361.  
  362.     Number := d;
  363.  
  364.     (* for all y in X such that x R y DO *)
  365.  
  366.     WITH Relation DO
  367.       u := Used;
  368.       FOR ArrayIndex := 1 TO u DO
  369.         yIndex := Array^[ArrayIndex];
  370.  
  371.         (* if Ny = 0 then call Traverse y *)
  372.  
  373.         IF ItemArrayPtr^[yIndex].Number = 0 THEN
  374.           Traverse (yIndex,TreatConflict);
  375.         END;
  376.  
  377.         (* assign N x <- Min (N x, N y) ;  F x := F x union F y *)
  378.  
  379.         IF ItemArrayPtr^[yIndex].Number < Number THEN
  380.           Number := ItemArrayPtr^[yIndex].Number; 
  381.         END;
  382.  
  383.         Union (Set,ItemArrayPtr^[yIndex].Set);
  384.       END;
  385.     END;
  386.  
  387.     (* IF N x = d *)
  388.  
  389.     IF Number = d THEN
  390.       cyclic := FALSE;
  391.       EmptyCycle := TRUE;
  392.  
  393.       (* then repeat *) 
  394.  
  395.       REPEAT
  396.         (* assign N (Top OF S) <- Infinity) ; F(Top OF S) <- F x *)
  397.  
  398.         Top := TopItem();
  399.         ItemArrayPtr^[Top].Number := MaxShortCard;
  400.  
  401.         IF Top # x THEN
  402.           Assign (ItemArrayPtr^[Top].Set, Set);
  403.           cyclic := TRUE;
  404.           EmptyCycle := EmptyCycle AND ItemArrayPtr^[Top].EmptyReadSet;
  405.         END
  406.  
  407.       (* until (Pop OF S) = x *)
  408.  
  409.       UNTIL PopItem() = x;
  410.  
  411.       IF cyclic THEN
  412.         EmptyCycle := EmptyCycle AND EmptyReadSet;
  413.         TreatConflict (EmptyCycle);
  414.       END;
  415.     END;
  416.       END;
  417.     END Traverse;
  418.  
  419.   PROCEDURE ComputeIncludesAndLookback;
  420.     VAR
  421.       State, maxState    : tStateIndex;
  422.       Transition, Item, RepItem    : tItemIndex;
  423.       TransItem        : tItem;
  424.       Production    : tProduction;
  425.       nullable        : BOOLEAN;
  426.     BEGIN
  427.       (* loesche bisherige Relation fuer neue Includesrelation *)
  428.  
  429.       ClearRelation;
  430.  
  431.       (* Betrachte alle States *)
  432.  
  433.       maxState := StateIndex;
  434.       FOR State := 1 TO maxState DO
  435.     WITH StateArrayPtr^[State] DO
  436.       
  437.       (* Betrachte alle Nichterminaluebergaenge *)
  438.  
  439.       FOR Transition := Items TO Items + Size - 1 DO
  440.         TransItem := ItemArrayPtr^[Transition];
  441.         IF TransItem.Rep = NonTermRep THEN
  442.  
  443.           (* Finde Situationen deren Produktion mit dem *)
  444.           (* zur Transition gehoerigen Nichterminal beginnen *)
  445.  
  446.           FOR Item := Items TO Items + Size - 1 DO
  447.         WITH ItemArrayPtr^[Item] DO
  448.           Production := ADR(ProdArrayPtr^[Prod]);
  449.           IF (Pos = 0) AND (Production^.Left = TransItem.Read) THEN
  450.             IF Pos < Production^.Len THEN
  451.               WindThrough (Next,Prod,Pos+1,Transition,nullable);
  452.               IF nullable THEN
  453.             (* Repraesentant beschaffen *)
  454.             RepItem := RepNo;
  455.             (* pruefen ob Nichtterminaluebergang *)
  456.             IF ItemArrayPtr^[RepItem].Rep = NonTermRep THEN
  457.               (* Include zu sich selbst ausfiltern, *)
  458.               (* da nicht konstruktiv bei Followberechnung *)
  459.               IF (RepItem # Transition) THEN 
  460.                 PutInRelation (RepItem,Transition); (* In Include eintragen *)
  461.               END;
  462.             END;
  463.               END;
  464.             ELSE
  465.               PutInRelation (Item,Transition); (* In Lookback eintragen *)
  466.             END;
  467.           END;
  468.         END;
  469.           END;
  470.         END;
  471.       END;
  472.     END;
  473.       END;
  474.     END ComputeIncludesAndLookback;
  475.   
  476.   PROCEDURE WindThrough (MyState: tStateIndex; MyProd: tProdIndex; MyPos: tIndex; Trans: tItemIndex; VAR nullable: BOOLEAN);
  477.     VAR
  478.       Item        : tItemIndex;
  479.       Production    : tProduction;
  480.     BEGIN
  481.       WITH StateArrayPtr^[MyState] DO
  482.  
  483.     (* finde zugehoeriges Item *)
  484.  
  485.     Item := Items;
  486.     LOOP
  487.       WITH ItemArrayPtr^[Item] DO
  488.         IF (Prod = MyProd) AND (Pos = MyPos) THEN
  489.           EXIT;
  490.         END;
  491.         INC (Item);
  492.       END;
  493.     END;
  494.  
  495.     WITH ItemArrayPtr^[Item] DO
  496.  
  497.       (* eindeutigen Repraesentanten beschaffen *)
  498.       (* jedoch mit speziellen (WITH-Statement) weiterarbeiten *)
  499.  
  500.       Item := ItemArrayPtr^[Item].RepNo;
  501.  
  502.       (* zugehoerige Production beschaffen *)
  503.  
  504.       Production := ADR(ProdArrayPtr^[Prod]);
  505.       IF Pos < Production^.Len THEN 
  506.  
  507.         (* Ende noch nicht ereicht *)
  508.  
  509.         WindThrough (Next, Prod, Pos+1, Trans, nullable);
  510.         IF nullable THEN 
  511.           IF ItemArrayPtr^[Item].Rep = NonTermRep THEN
  512.  
  513.         (* Include zu sich selbst ausfiltern, *)
  514.         (* da nicht konstruktiv bei Followberechnung *)
  515.  
  516.         IF (Item # Trans) THEN 
  517.  
  518.           (* In Include eintragen *)
  519.  
  520.           PutInRelation (Item,Trans);
  521.         END;
  522.           END;
  523.           nullable := IsElement (Read, Nullables);
  524.         END;
  525.       ELSE
  526.  
  527.         (* Ende der Produktion wurde erreicht *)
  528.  
  529.         nullable := TRUE;
  530.         PutInRelation (Item, Trans);
  531.       END;
  532.     END;
  533.       END;
  534.     END WindThrough;
  535.  
  536.   PROCEDURE ComputeLA;
  537.     VAR 
  538.       Index    : tIndex;
  539.       Item    : tItemIndex;
  540.       maxItem    : tItemIndex;
  541.       lookbackindex    : tItemIndex;
  542.       u        : tIndex;
  543.     BEGIN
  544.       
  545.       (* fuer alle Items, die eine Reduktion darstellen *)
  546.  
  547.       maxItem := ItemIndex;
  548.       FOR Item :=1 TO maxItem DO
  549.     WITH ItemArrayPtr^[Item] DO
  550.       IF Rep = RedRep THEN
  551.  
  552.         (* Berechne Look Ahead Set *)
  553.  
  554.         (* fuer alle Item in Lookback *)
  555.  
  556.         WITH Relation DO
  557.           u := Used;
  558.           FOR Index := 1 TO u DO
  559.         lookbackindex := Array^[Index];
  560.         
  561.         (* fuege Follow(lookback) hinzu *)
  562.  
  563.         Union (Set, ItemArrayPtr^[lookbackindex].Set);
  564.           END;
  565.         END;
  566.       END;
  567.     END;
  568.       END;
  569.     END ComputeLA;
  570.   
  571.   PROCEDURE TreatReadConflict (empty: BOOLEAN);
  572.   BEGIN
  573.     IF NOT reportedError THEN
  574.       (* do not report this fact
  575.       ErrorMessage (eNotLRk,eInformation,0,0);
  576.       *)
  577.       reportedError := TRUE;
  578.     END;
  579.   END TreatReadConflict;
  580.  
  581.   PROCEDURE TreatFollowConflict (empty: BOOLEAN);
  582.   BEGIN
  583.     IF NOT empty THEN
  584.       IF NOT reportedError THEN
  585.     (* do not report this fact
  586.     ErrorMessage (eNotLRk,eInformation,0,0);
  587.     *)
  588.     reportedError := TRUE;
  589.       END;
  590.     END;
  591.   END TreatFollowConflict;
  592.  
  593.   PROCEDURE ClearRelation;
  594.     VAR Item, maxItem    : tItemIndex;
  595.     BEGIN
  596.       maxItem := ItemIndex;
  597.       FOR Item := 1 TO maxItem DO
  598.     ItemArrayPtr^[Item].Relation.Used := 0;
  599.       END;
  600.     END ClearRelation;
  601.  
  602.   PROCEDURE PutInRelation (Rel: tItemIndex; NT: tItemIndex);
  603.     VAR i, u    : tIndex;
  604.     BEGIN
  605.  
  606.       (* zu bearbeitende Relation auswaehlen *)
  607.  
  608.       WITH ItemArrayPtr^[Rel].Relation DO
  609.  
  610.     (* pruefen ob Eintrag bereits vorhanden *)
  611.  
  612.     u := Used;
  613.     FOR i := 1 TO u DO
  614.       IF Array^[i] = NT THEN RETURN; END;
  615.     END;
  616.     
  617.     (* eventuell Speicher beschaffen *)
  618.  
  619.     IF Used = 0 THEN
  620.       MakeArray (Array,Count,TSIZE(tIndex));
  621.     ELSIF Used >= Count THEN
  622.       ExtendArray (Array,Count,TSIZE(tIndex));
  623.     END;
  624.     INC (Used);
  625.     Array^[Used] := NT; 
  626.       END;
  627.     END PutInRelation;
  628.  
  629.   MODULE ItemStack;
  630.  
  631.     IMPORT tItemIndexList, tItemIndex, TSIZE, MakeArray, ExtendArray, eInternal, eFatal, ERROR;
  632.  
  633.     EXPORT ClearItemStack, ItemDepth, PushItem, PopItem, TopItem;
  634.  
  635.    CONST InitItemStackCount = 10;
  636.  
  637.    VAR Stack    : tItemIndexList;
  638.  
  639.     PROCEDURE ClearItemStack;
  640.       BEGIN
  641.     Stack.Used := 0;
  642.       END ClearItemStack;
  643.  
  644.     PROCEDURE PushItem (Item: tItemIndex);
  645.       BEGIN
  646.     WITH Stack DO
  647.       INC (Used);
  648.       IF Used > Count THEN
  649.         IF Count = 0 THEN
  650.           Count := InitItemStackCount;
  651.           MakeArray (Array,Count,TSIZE(tItemIndex));
  652.         ELSE
  653.           ExtendArray (Array,Count,TSIZE(tItemIndex));
  654.         END;
  655.       END;
  656.       Array^[Used] := Item;
  657.     END;
  658.       END PushItem;
  659.  
  660.     PROCEDURE PopItem ():tItemIndex;
  661.       VAR Item    : tItemIndex;
  662.       BEGIN
  663.     WITH Stack DO
  664.       IF Used < 1 THEN
  665.         ERROR ('PopItem on empty Stack');
  666.       END;
  667.       Item := Array^[Used];
  668.       DEC (Used);
  669.       RETURN Item;
  670.     END;
  671.       END PopItem;
  672.  
  673.     PROCEDURE TopItem ():tItemIndex;
  674.       BEGIN
  675.     WITH Stack DO
  676.       RETURN Array^[Used];
  677.     END;
  678.       END TopItem;
  679.  
  680.     PROCEDURE ItemDepth ():CARDINAL;
  681.       BEGIN
  682.     RETURN Stack.Used;
  683.       END ItemDepth;
  684.  
  685.     BEGIN
  686.       Stack.Used := 0;
  687.       Stack.Count :=0;
  688.     END ItemStack;
  689.  
  690.   PROCEDURE ClearNumbers;
  691.   VAR i, maxi    : tItemIndex;
  692.     BEGIN
  693.       maxi := ItemIndex;
  694.       FOR i:=1 TO maxi DO
  695.     WITH ItemArrayPtr^[i] DO
  696.       IF Rep = NonTermRep THEN
  697.         Number := 0;
  698.       ELSE
  699.         Number := MaxShortCard;
  700.       END;
  701.     END;
  702.       END;
  703.     END ClearNumbers;
  704.   
  705.   PROCEDURE ERROR (a: ARRAY OF CHAR);
  706.   VAR s    : tString;
  707.   BEGIN
  708.     ArrayToString (a, s);
  709.     ErrorMessageI (eInternal, eFatal, NoPosition, eString, ADR (s));
  710.   END ERROR;
  711.  
  712. BEGIN 
  713.   reportedError := FALSE;
  714. END Lookahead.
  715.